package com.ecoolex.ying.space.admin.graphql;

import static com.ecoolex.framework.web.api.graphql2.annotation.GraphQL2Module.Type.Admin;

import java.util.List;
import java.util.stream.Collectors;

import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.NonNull;

import com.alibaba.fastjson.JSON;
import com.ecoolex.framework.common.annotation.Description;
import com.ecoolex.framework.common.enums.ResultCode;
import com.ecoolex.framework.common.pojo.Page;
import com.ecoolex.framework.common.pojo.Pagination;
import com.ecoolex.framework.common.pojo.Sorting;
import com.ecoolex.framework.common.util.Assert;
import com.ecoolex.framework.common.util.BeanUtil;
import com.ecoolex.framework.common.util.Check;
import com.ecoolex.framework.modularize.api.auth.admin.AdminMemberAuthority;
import com.ecoolex.framework.modularize.api.auth.annotation.AdminAuthoritativeRegister;
import com.ecoolex.framework.modularize.api.service.storage.FileSize;
import com.ecoolex.framework.modularize.api.service.storage.MimeType;
import com.ecoolex.framework.modularize.api.service.storage.StorageInfo;
import com.ecoolex.framework.modularize.api.service.storage.StorageService;
import com.ecoolex.framework.modularize.api.service.storage.Upload;
import com.ecoolex.framework.modularize.api.service.storage.UploadLimit;
import com.ecoolex.framework.modularize.api.service.storage.UploadSource;
import com.ecoolex.framework.web.api.graphql2.annotation.GraphQL2Module;
import com.ecoolex.framework.web.api.graphql2.annotation.MutationField;
import com.ecoolex.framework.web.api.graphql2.annotation.QueryField;
import com.ecoolex.framework.web.api.graphql2.annotation.Source;
import com.ecoolex.framework.web.api.graphql2.annotation.TypeField;
import com.ecoolex.ying.space.admin.core.AdminConstant;
import com.ecoolex.ying.space.entity.EstateProjectActivityGoods;
import com.ecoolex.ying.space.entity.EstateProjectActivityGoodsCategory;
import com.ecoolex.ying.space.entity.EstateProjectActivityGoods.Column;
import com.ecoolex.ying.space.entity.PickGoodsWithBLOBs;
import com.ecoolex.ying.space.pojo.AddEstateProjectActivityGoodsDTO;
import com.ecoolex.ying.space.pojo.EditEstateProjectActivityGoodsDTO;
import com.ecoolex.ying.space.ws.EstateProjectActivityService;
import com.ecoolex.ying.space.ws.PickGoodsService;
import com.google.common.collect.Lists;

@GraphQL2Module(type = Admin, description = "地产项目活动商品管理")
@AdminAuthoritativeRegister(parentKey = AdminConstant.AUTH_MODULE_KEY, key = EstateProjectActivityGoodsGraphql.AUTH, name = "地产项目活动商品管理")
public class EstateProjectActivityGoodsGraphql {

	public static final String AUTH = AdminConstant.AUTH_MODULE_KEY + "-ESTATE-PROJECT-ACTIVITY-GOODS";
	
	private static final String AUTH_ADD = AUTH + "-ADD";
	
	private static final String AUTH_EDIT = AUTH + "-EDIT";
	
	private static final String AUTH_DEL = AUTH + "-DEL";
	
	private static final String AUTH_GET = AUTH + "-GET";
	
	private static final String AUTH_QUERY = AUTH + "-QUERY";
	
	private static final String AUTH_PRIMARY_QUERY = AUTH + "-PRIMARY-QUERY";
	
	private static final String AUTH_ONLINE = AUTH + "-ONLINE";
	
	private static final String AUTH_OFFLINE = AUTH + "-OFFLINE";
	
	@Reference
	private EstateProjectActivityService estateProjectActivityService;
	
	@Autowired
    private StorageService storageService;
	
	@Reference
	private PickGoodsService pickGoodsService;
	
	@TypeField(type = EstateProjectActivityGoods.class, field = "activityCoverImage", description = "地产项目活动商品封面图")
    public StorageInfo coverImage(@Source EstateProjectActivityGoods source) {
        return storageService.get(source.getActivityCoverImage());
    }
	
	@TypeField(type = EstateProjectActivityGoods.class, field = "images", description = "地产项目活动商品轮播图片")
	public List<StorageInfo> images(@Source EstateProjectActivityGoods source){
		if(Check.notNullOrTrimEmpty(source.getImages())) {
			return JSON.parseArray(source.getImages(), String.class).stream()
				.map(storageService::get)
				.filter(Check::notNull)
				.collect(Collectors.toList());
		}
		return Lists.newArrayList();
	}
	
	@TypeField(type = EstateProjectActivityGoods.class,field = "activityGoodsCategory",description = "所属活动商品分类")
	public EstateProjectActivityGoodsCategory category(@Source EstateProjectActivityGoods source) {
		return estateProjectActivityService.getEstateProjectActivityGoodsCategory(source.getActivityCategoryId());
	}
	
	@TypeField(type = EstateProjectActivityGoods.class,field = "canDelete",description = "能删除")
	public boolean canDelete(@Source EstateProjectActivityGoods source, AdminMemberAuthority user) {
		return user.auth(AUTH_DEL);
	}
	
	@TypeField(type = EstateProjectActivityGoods.class,field = "canOnline",description = "能上线")
	public boolean canOnline(@Source EstateProjectActivityGoods source, AdminMemberAuthority user) {
		return !source.getOnline() && user.auth(AUTH_ONLINE);
	}
	
	@TypeField(type = EstateProjectActivityGoods.class,field = "canOffline",description = "能下线")
	public boolean canOffline(@Source EstateProjectActivityGoods source, AdminMemberAuthority user) {
		return source.getOnline() && user.auth(AUTH_OFFLINE);
	}
	
	@QueryField(field = "estateProjectActivityGoods" , description = "地产项目活动商品详情")
	@AdminAuthoritativeRegister(parentKey = AUTH, key = AUTH_GET, name = "地产项目活动商品详情")
	public EstateProjectActivityGoods get(@NonNull Integer activityGoodsId, AdminMemberAuthority user) {
		user.assertAuth(AUTH_GET);
		return estateProjectActivityService.getEstateProjectActivityGoods(activityGoodsId);
	}
	
	@QueryField(field = "estateProjectActivityGoodsList" , description = "地产项目活动商品列表")
	@AdminAuthoritativeRegister(parentKey = AUTH, key = AUTH_QUERY, name = "地产项目活动商品列表")
	public Pagination<EstateProjectActivityGoods> query(String activityName,@Description({"二级分类Id"}) Integer activityCategoryId,Boolean online,@NonNull Sorting[] sorts,@NonNull Page page, AdminMemberAuthority user) {
		user.assertAuth(AUTH_QUERY);
		return estateProjectActivityService.queryEstateProjectActivityGoods(activityName,activityCategoryId,online,sorts, page);
	}
	
	@QueryField(field = "estateProjectActivityGoodsListForPrimaryCategory" , description = "一级分类下地产项目活动商品列表")
	@AdminAuthoritativeRegister(parentKey = AUTH, key = AUTH_PRIMARY_QUERY, name = "一级分类下地产项目活动商品列表")
	public Pagination<EstateProjectActivityGoods> queryForPrimaryCategory(String activityName,@Description({"一级分类Id"})@NonNull Integer activityCategoryId,Boolean online,@NonNull Sorting[] sorts,@NonNull Page page, AdminMemberAuthority user) {
		user.assertAuth(AUTH_PRIMARY_QUERY);
		return estateProjectActivityService.queryEstateProjectActivityGoodsForPrimaryCategory(activityName,activityCategoryId,online,sorts, page);
	}
	
	@MutationField(field = "uploadEstateProjectActivityGoodsCoverImage", description = { "上传地产项目活动商品封面图" })
    public StorageInfo uploadEstateProjectActivityImage(@NonNull Upload request, AdminMemberAuthority user) {
        if (!user.auth(AUTH_ADD) && !user.auth(AUTH_EDIT)) {
            user.notAuthority();
        }
        UploadSource uploadSource = new UploadSource("EstateProjectActivityGoods", "ActivityCoverImage");
        UploadLimit uploadLimit = new UploadLimit();
        uploadLimit.setMaxSize(FileSize.MB.byteLength(10));
        uploadLimit.setAllowMimeType(MimeType.IMAGE.commons());

        return storageService.upload(request, uploadSource, uploadLimit);
    }
	
	@MutationField(field = "uploadEstateProjectActivityGoodsImages", description = { "上传地产项目商品轮播图片" })
    public StorageInfo uploadEstateProjectActivityGoodsImages(@NonNull Upload request, AdminMemberAuthority user) {
        if (!user.auth(AUTH_ADD) && !user.auth(AUTH_EDIT)) {
            user.notAuthority();
        }
        UploadSource uploadSource = new UploadSource("EstateProjectActivityGoods", "Images");
        UploadLimit uploadLimit = new UploadLimit();
        uploadLimit.setMaxSize(FileSize.MB.byteLength(10));
        uploadLimit.setAllowMimeType(MimeType.IMAGE.commons());

        return storageService.upload(request, uploadSource, uploadLimit);
    }
	
	@MutationField(field = "uploadEstateProjectActivityGoodsDetail", description = { "上传地产项目商品详情" })
    public StorageInfo uploadEstateProjectActivityGoodsDetail(@NonNull Upload request, AdminMemberAuthority user) {
        if (!user.auth(AUTH_ADD) && !user.auth(AUTH_EDIT)) {
            user.notAuthority();
        }
        UploadSource uploadSource = new UploadSource("EstateProjectActivityGoods", "Detail");
        UploadLimit uploadLimit = new UploadLimit();
        uploadLimit.setMaxSize(FileSize.MB.byteLength(10));
        uploadLimit.setAllowMimeType(MimeType.IMAGE.commons());

        return storageService.upload(request, uploadSource, uploadLimit);
    }
	
	@MutationField(field = "addEstateProjectActivityGoods", description = "添加地产项目活动商品")
    @AdminAuthoritativeRegister(parentKey = AUTH, key = AUTH_ADD, name = "添加地产项目活动商品")
	public EstateProjectActivityGoods add(@NonNull AddEstateProjectActivityGoodsDTO record, AdminMemberAuthority user) {
		user.assertAuth(AUTH_ADD);
		EstateProjectActivityGoodsCategory category = estateProjectActivityService.getEstateProjectActivityGoodsCategory(record.getActivityCategoryId());
		Assert.isTrue(Check.notNull(category),ResultCode.VERIFY.build(1), "二级分类Id={}，不存在",record.getActivityCategoryId());
		PickGoodsWithBLOBs pickGoods = pickGoodsService.getPickGoodsById(record.getPickGoodsId());
		Assert.isTrue(Check.notNull(pickGoods),ResultCode.VERIFY.build(2), "优选商品Id={}，不存在",record.getPickGoodsId());
		//同一个商品在一个二级分类下只能存在一次
		EstateProjectActivityGoods old = estateProjectActivityService.getByPickGoodsIdAndActivityCategoryId(record.getPickGoodsId(), record.getActivityCategoryId());
		Assert.isTrue(Check.isNull(old),ResultCode.VERIFY.build(3), "此二级分类下已经存在这个商品");
		return estateProjectActivityService.addEstateProjectActivityGoods(record, user.userName());
	}
	
	@MutationField(field = "editEstateProjectActivityGoods", description = "编辑地产项目活动商品")
    @AdminAuthoritativeRegister(parentKey = AUTH, key = AUTH_EDIT, name = "编辑地产项目活动商品")
	public EstateProjectActivityGoods edit(@NonNull EditEstateProjectActivityGoodsDTO record, AdminMemberAuthority user) {
		user.assertAuth(AUTH_EDIT);
		EstateProjectActivityGoods old = estateProjectActivityService.getEstateProjectActivityGoods(record.getActivityGoodsId());
		Assert.isTrue(Check.notNull(old),ResultCode.VERIFY.build(1), "地产项目活动商品不存在");
		BeanUtil.copy(record,
            old,
            Lists.newArrayList(
            		Column.pickGoodsId,
            		Column.online,
                    Column.deleted,
                    Column.createUser,
                    Column.createTime).stream().map(Column::getJavaProperty).toArray(String[]::new));
		return estateProjectActivityService.editEstateProjectActivityGoods(old, user.userName());
	}
	
	@MutationField(field = "delEstateProjectActivityGoods", description = "删除地产项目活动商品")
    @AdminAuthoritativeRegister(parentKey = AUTH, key = AUTH_DEL, name = "删除地产项目活动商品")
	public boolean delete(@NonNull Integer activityGoodsId, AdminMemberAuthority user) {
		user.assertAuth(AUTH_DEL);
		EstateProjectActivityGoods old = estateProjectActivityService.getEstateProjectActivityGoods(activityGoodsId);
		Assert.isTrue(Check.notNull(old),ResultCode.VERIFY.build(1), "地产项目活动商品不存在");
		estateProjectActivityService.deleteEstateProjectActivityGoods(old, user.userName());
		return true;
	}
	
	@MutationField(field = "onlineEstateProjectActivityGoods", description = "上线地产项目活动商品")
    @AdminAuthoritativeRegister(parentKey = AUTH, key = AUTH_ONLINE, name = "上线地产项目活动商品")
	public boolean online(@NonNull Integer activityGoodsId, AdminMemberAuthority user) {
		user.assertAuth(AUTH_ONLINE);
		EstateProjectActivityGoods old = estateProjectActivityService.getEstateProjectActivityGoods(activityGoodsId);
		Assert.isTrue(Check.notNull(old),ResultCode.VERIFY.build(1), "地产项目活动商品不存在");
		estateProjectActivityService.onlineEstateProjectActivityGoods(old, user.userName());
		return true;
	}
	
	@MutationField(field = "offlineEstateProjectActivityGoods", description = "下线地产项目活动商品")
    @AdminAuthoritativeRegister(parentKey = AUTH, key = AUTH_OFFLINE, name = "下线地产项目活动商品")
	public boolean offline(@NonNull Integer activityGoodsId, AdminMemberAuthority user) {
		user.assertAuth(AUTH_OFFLINE);
		EstateProjectActivityGoods old = estateProjectActivityService.getEstateProjectActivityGoods(activityGoodsId);
		Assert.isTrue(Check.notNull(old),ResultCode.VERIFY.build(1), "地产项目活动商品不存在");
		estateProjectActivityService.offlineEstateProjectActivityGoods(old, user.userName());
		return true;
	}
}
